package com.sc.nft.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiniu.util.Auth;
import com.sc.nft.annotation.DistributedLock;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.entity.StaticData;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.StaticDataService;
import com.sc.nft.util.PropertiesUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 服务接口实现
 *
 * @author Sun
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2022-05-29 17:37:58
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class StaticDataServiceImpl implements StaticDataService {
    private final StaticDataDao staticDataDao;

    private final RedisTemplate redisTemplate;

    @Override
    public HashMap<String, String> getQiniuToken() {
        String accessKey = PropertiesUtil.getProperty("QI_NIU_YUN_ACCESS_KEY");
        String secretKey = PropertiesUtil.getProperty("QI_NIU_YUN_SECRET_KEY");
        String bucket = PropertiesUtil.getProperty("QI_NIU_YUN_BUCKET");

        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        HashMap<String, String> map = new HashMap<>();
        map.put("uptoken", upToken);
        return map;
    }

    @Override
    public HashMap<String, String> getStaticData() {
        LambdaQueryWrapper<StaticData> staticDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
        staticDataLambdaQueryWrapper.eq(StaticData::getIsShowInterface, true);
        StaticData staticData = new StaticData();
        List<StaticData> list = staticData.selectList(staticDataLambdaQueryWrapper);
        HashMap<String, String> map = new HashMap<>();
        for (StaticData data : list) {
            String type = data.getType();
            String value = data.getValue();
            map.put(type, value);
        }
        return map;
    }

    @Override
    public List<StaticData> getAdminStaticData() {
        LambdaQueryWrapper<StaticData> staticDataLambdaQueryWrapper = new LambdaQueryWrapper<>();
        staticDataLambdaQueryWrapper.eq(StaticData::getIsShowManage, true);
        StaticData staticData = new StaticData();
        List<StaticData> list = staticData.selectList(staticDataLambdaQueryWrapper);
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStaticData(String type, String value) {
        String key = StrUtil.format("{}:{}", RedisKeyEnum.STATIC_DATA_TYPE, type);
        redisTemplate.delete(key);
        Boolean b = staticDataDao.updateStaticData(type, value);
        if (!b) {
            throw new GlobalRunTimeException("修改失败");
        }
    }

    @Override
    public StaticData getByType(String type) {
        String key = StrUtil.format("{}:{}", RedisKeyEnum.STATIC_DATA_TYPE, type);
        Boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            return JSONObject.parseObject(Convert.toStr(redisTemplate.opsForValue().get(StrUtil.format("{}:{}", RedisKeyEnum.STATIC_DATA_TYPE, type))), StaticData.class);
        }
        StaticData byType = staticDataDao.getByType(type);
        redisTemplate.opsForValue().set(key, JSONObject.toJSONString(byType), 15, TimeUnit.MINUTES);
        return byType;
    }

    @Override
    public Map<String, String> listByTypes(List<String> types) {
        if (CollectionUtils.isEmpty(types)) {
            return Collections.emptyMap();
        }
        LambdaQueryWrapper<StaticData> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(StaticData::getType, StaticData::getValue);
        wrapper.in(StaticData::getType, types);
        List<StaticData> objects = staticDataDao.list(wrapper);
        return objects.stream().collect(Collectors.toMap(StaticData::getType, StaticData::getValue));
    }

    @Override
    public void edit(String type, String value, String remark) {
        StaticData data = getByType(type);
        if (Objects.isNull(data)) {
            StaticData staticData = new StaticData();
            staticData.setType(type);
            staticData.setValue(value);
            staticData.setRemark(remark);
            staticData.setIsShowInterface(1);
            staticData.setIsShowManage(1);
            staticData.insert();
        } else {
            staticDataDao.updateStaticData(type, value);
        }
    }

    public Boolean isReadOne(String type) {
        UserInfo user = UserPool.getUser();
        Boolean bit = redisTemplate.opsForValue().getBit("isRead:" + type, user.getId());
        if (bit) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    @Override
    public void readAndAgree(String type) {
        UserInfo user = UserPool.getUser();
        redisTemplate.opsForValue().setBit("isRead:" + type, user.getId(), Boolean.TRUE);
    }
}